package future;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.function.Consumer;

public class ListenableFutureImpl<T> implements ListenableFuture<T> {
    private final Callable<T> callable;
    private final List<Consumer<T>> listeners = new ArrayList<>();
    private final Object lock = new Object();
    private T result;
    private Throwable exception;
    private boolean done;

    public ListenableFutureImpl(Callable<T> callable) {
        this.callable = callable;
    }

    @Override
    public void addListener(Consumer<T> listener, Executor executor) {
        synchronized (lock) {
            listeners.add(listener);
            if (done) {
                notifyListener(listener, executor, result);
            }
        }
    }

     //简化版addListener，不使用Executor
     @Override
     public void addListener(Consumer<T> listener) {
         addListener(listener, Executors.newSingleThreadExecutor()); // 或者使用其他默认的Executor
     }


    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        // 实现取消逻辑（如果需要的话）
        return false;
    }

    @Override
    public boolean isCancelled() {
        // 实现检查是否被取消的逻辑（如果需要的话）
        return false;
    }

    @Override
    public boolean isDone() {
        synchronized (lock) {
            return done;
        }
    }

    @Override
    public T get() throws InterruptedException, ExecutionException {
        synchronized (lock) {
            while (!done) {
                lock.wait(); // 等待任务完成
            }
            if (exception != null) {
                throw new ExecutionException(exception);
            }
            return result;
        }
    }

    @Override
    public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        synchronized (lock) {
            long remaining = unit.toMillis(timeout);
            while (!done && remaining > 0) {
                lock.wait(remaining); // 等待任务完成或超时
                remaining = unit.toMillis(timeout) - System.currentTimeMillis() + System.nanoTime() / 1_000_000; // 更新剩余时间（考虑等待期间的时间流逝）
                // 注意：上面的剩余时间计算可能不是完全准确的，因为它没有考虑到wait()方法可能在中途被中断的情况。
                // 在实际应用中，你可能需要使用更精确的时间计算方法，或者简单地使用一个固定的等待时间和循环次数。
                // 这里为了简化，我们假设wait()方法不会被中断，并且时间流逝是线性的。
            }
            if (!done) {
                throw new TimeoutException();
            }
            if (exception != null) {
                throw new ExecutionException(exception);
            }
            return result;
        }
    }

    // 用于启动任务并设置结果的方法
    public ListenableFutureImpl<T> start() {
        synchronized (lock) {
            new Thread(() -> {
                try {
                    T result = callable.call();
                    setResultAndNotify(result, null);
                } catch (Exception e) {
                    setResultAndNotify(null, e);
                }
            }).start();
            return this;
        }
    }

    // 用于执行任务并设置结果的方法
    public ListenableFutureImpl<T> execute() {
        synchronized (lock) {
            Executors.newSingleThreadExecutor().execute(() -> {
                try {
                    T result = callable.call();
                    setResultAndNotify(result, null);
                } catch (Exception e) {
                    setResultAndNotify(null, e);
                }
            });
            return this;
        }
    }

    // 用于设置任务结果并通知监听器的方法（应该在任务完成的线程中调用）
    private void setResultAndNotify(T result, Throwable exception) {
        synchronized (lock) {
            this.result = result;
            this.exception = exception;
            this.done = true;
            lock.notifyAll(); // 唤醒等待的线程
            notifyListeners();
            //notifyListeners(result,exception);
        }
    }

    // 通知所有监听器
    private void notifyListeners() {
        listeners.forEach(listener -> notifyListener(listener, Executors.newSingleThreadExecutor()));
    }

    private void notifyListeners(T result, Throwable exception) {
        for (Consumer<T> listener : listeners) {
            // 这里可以使用默认的Executor，或者从addListener传入的Executor
            notifyListener(listener, Executors.newSingleThreadExecutor(), result, exception);
        }
    }


    // 通知单个监听器
    private void notifyListener(Consumer<T> listener, Executor executor, T result, Throwable exception) {
        if (exception == null) {
            executor.execute(() -> listener.accept(result));
        } else {
            // 任务失败，可以选择在这里处理异常，或者将异常传递给监听器
            // 例如，如果监听器期望处理异常，可以创建一个扩展的Consumer接口，或者封装异常和结果在一个对象中传递给监听器
            // 这里为了简化，我们假设监听器不处理异常，只在任务成功时被调用
            // 如果需要传递异常给监听器，可以修改listener.accept的调用，传递一个包含异常的对象或信息
            // 处理异常，例如记录日志或调用监听器的错误处理方法（如果需要）
            // 这里为了简化，只记录日志
            System.err.println("Task completed with exception: " + exception);
        }
    }

    private void notifyListener(Consumer<T> listener, Executor executor,T result) {
        notifyListener(listener,executor,result,exception);
    }

    private void notifyListener(Consumer<T> listener, Executor executor) {
        notifyListener(listener,executor,result,exception);
    }

}


